package com.ants.auth.config.oauth2;

import com.ants.auth.service.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.*;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import java.util.ArrayList;
import java.util.List;

/**
 * @author : 蚂蚁会花呗
 * @date : 2023-08-07 15:04
 * oauth2 授权服务器配置
 * client模式
 * post请求
 * http://localhost:8086/ants-boot-oauth2-local/oauth/token?grant_type=client_credentials&scope=select&client_id=client_1&client_secret=123456
 * password模式
 * post请求
 * http://localhost:8086/ants-boot-oauth2-local/oauth/token?username=user_1&password=123456&grant_type=password&scope=select&client_id=client_2&client_secret=123456
 *
 *
 **/
@Configuration
@EnableAuthorizationServer
public class OAuth2ServerConfig extends AuthorizationServerConfigurerAdapter {
    private static final String DEMO_RESOURCE_ID = "order";

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private JwtAccessTokenConverter accessTokenConverter;

    @Autowired
    private UserServiceImpl userServiceDetail;

    @Autowired
    private JwtTokenEnhancer jwtTokenEnhancer;


    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //配置两个客户端,一个用于password认证一个用于client认证
        clients.inMemory().withClient("client_1")
                .resourceIds(DEMO_RESOURCE_ID)
                .authorizedGrantTypes("password", "refresh_token")
                .scopes("all")
                //.secret是为了判断传过来的值和这里设置的要相等
                //这里我使用了new BCryptPasswordEncoder，是因为 WebSecurityConfig 中配置了 SHA-256+随机盐+密钥进行加密 bean
                //因此为了密码校验通过，必须使用同等的方法进行加密后判断
                .secret(new BCryptPasswordEncoder().encode(("123456")))
                //设置 client_1 令牌过期时间秒 2个小时,refreshTokenValiditySeconds设置的是刷新时间
                .accessTokenValiditySeconds(60 * 60 * 2)
                .refreshTokenValiditySeconds(60 * 60 * 5);
                /*.and().withClient("client_2")
                .resourceIds(DEMO_RESOURCE_ID)
                .authorizedGrantTypes("password", "refresh_token")
                .scopes("select")
                .authorities("client")
                .secret(new BCryptPasswordEncoder().encode(("123456")))
                //设置client_2令牌过期时间秒 2个小时
                .accessTokenValiditySeconds(60 * 60 * 2)
                .refreshTokenValiditySeconds(60 * 60 * 5);*/
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .tokenServices(tokenService())
                .userDetailsService(userServiceDetail)
                .authenticationManager(authenticationManager);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients();
    }

    @Bean
    public AuthorizationServerTokenServices tokenService() {
        DefaultTokenServices service = new DefaultTokenServices();
        service.setSupportRefreshToken(true);
        service.setTokenStore(tokenStore);
        //令牌增强
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        List<TokenEnhancer> tokenEnhancers = new ArrayList<>();
        tokenEnhancers.add(jwtTokenEnhancer);
        tokenEnhancers.add(accessTokenConverter);
        tokenEnhancerChain.setTokenEnhancers(tokenEnhancers);
        service.setTokenEnhancer(tokenEnhancerChain);
        service.setAccessTokenValiditySeconds(60 * 60 * 2); // 令牌默认有效期2小时
        service.setRefreshTokenValiditySeconds(60 * 60 * 5); // 刷新令牌默认有效期5小时
        return service;
    }

}
